﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime;
using System.Runtime.Serialization;
using DataBase;

namespace Database
{
    [DataContract]
    public class DBmediator : DataBaseImpl
    {
        [DataMember]
        private DataBase dataBase;
        [DataMember]
        private SQLInit sql_init;

        public DBmediator(){
            //director
            User admin = new User("Gilad", "Sabari", "Gilad", "123", "bla@bla.com");
            dataBase = new DataBase(admin);
            sql_init = new SQLInit();
     //       Console.WriteLine("1111");
            sql_init.initDataBase(this);
        }

//        public void init(){
 //           sql_init.initDataBase(this);
 //       }

        //return forums in database
        public SortedDictionary<int, Forum> getForums() {
            return this.dataBase.getForums();
        }

        //return director ->מנהל על  
        public User getDirector() {
            return this.dataBase.getDirector();
        }

        //return SortedDictionary <int, string> : int -> id, string -> the forums titles
        public SortedDictionary<int, string> dataBasetoString() {
            SortedDictionary<int, string> titles = new SortedDictionary<int, string>();
            foreach (int id in dataBase.getForums().Keys) {
                titles.Add(id, dataBase.getForums()[id].getTitle());
            }
            return titles;
        }

        //return the number of forums in database
        public int getNumOfForums()
        {
            return dataBase.getForums().Count;
        }
        //set the number of forums in database
        public void setIdForForums(int num)
        {
            dataBase.setIdForForums(num);
        }

        /////////////////////////////   Forums    ////////////////////////////////////////////////////

        public Forum getForum(int forumId) {
            return dataBase.getForum(forumId);
        }

        public int addForum(string title, User admin) {
            int id = dataBase.addForum(title, admin);
            sql_init.addForum(title, id, admin.getUserName(), admin.getName(), admin.getLastName(), admin.getPassword(), admin.getEmail());
            return id;
        }

        public string getForumTitle(int forumId) {
            if (dataBase.getForums().ContainsKey(forumId)) 
                return dataBase.getForums()[forumId].getTitle();
            else
                return null;
        }

        public void setForumTitle(int forumId, string title){
            if (dataBase.getForums().ContainsKey(forumId))
            {
                dataBase.getForum(forumId).setTitle(title);
                //update database
                sql_init.updateForumTitle(forumId, title);
            }

        }

        public void setIdForSubForums(int forumId, int numForId){
            if (dataBase.getForums().ContainsKey(forumId))
                dataBase.getForum(forumId).setIdForSubForums(numForId);
        }
  
        public User getForumAdmin(int forumId) {
            if (dataBase.getForums().ContainsKey(forumId))
                return dataBase.getForums()[forumId].getAdmin();
            else
                return null;
        }

        public SortedDictionary<string, User> getForumUsers(int forumId) {
            if (dataBase.getForums().ContainsKey(forumId))
                return dataBase.getForums()[forumId].getUsers();
            else
                return null;
        }

        public bool isForumUser(int forumId, string user){
            if (dataBase.getForums().ContainsKey(forumId))
                return dataBase.getForum(forumId).containsUser(user);
            else 
                return false;
        }


        /////////////////////////////         SubForums        ////////////////////////////////////////////////////

        public SubForum getSubForum(int forumId, int subForumId)
        {
            if (dataBase.getForums().ContainsKey(forumId))
                return dataBase.getForum(forumId).getSubForum(subForumId);
            else
                return null;
        }

        public int addSubForum(int forumId, string title)
        {
            if (dataBase.getForums().ContainsKey(forumId)){
                User admin = dataBase.getForum(forumId).getAdmin();
                int subForumId = dataBase.getForum(forumId).addSubForum(title, admin);
                //update database
                sql_init.addSubForum(subForumId, title, forumId, admin.getUserName());
                return subForumId;
            }
            else
                return - 1;
        }

        public bool removeSubForum(int forumId, int subForumId)
        {
            if (dataBase.getForums().ContainsKey(forumId))
                return dataBase.getForum(forumId).removeSubForum(subForumId);
            else
                return false;
        }

        public void setSubForumTitle(int forumId, int subForumId, string title)
        {
            if (dataBase.getForums().ContainsKey(forumId))
            {
                dataBase.getForum(forumId).getSubForum(subForumId).setTitle(title);
                sql_init.updateSubForumTitle(subForumId, forumId, title);
            }
        }

        public string getSubForumTitle(int forumId, int subForumId)
        {
            if (dataBase.getForums().ContainsKey(forumId))
                return dataBase.getForum(forumId).getSubForum(subForumId).getTitle();
            else
                return null;
        }

        public bool addSubForumModerator(int forumId, int subForumId, string uname)
        {
            if (dataBase.getForums().ContainsKey(forumId))
            {
                User moderator = dataBase.getForum(forumId).getRegUser(uname);
                bool added = dataBase.getForum(forumId).getSubForum(subForumId).addModerator(moderator);
                //update DataBase 
                if (added)
                    sql_init.addSubForumModerator(forumId, subForumId, uname);
                return added;
            }
            else
                return false;
        }

        public bool removeSubForumModerator(int forumId, int subForumId, string uname)
        {
            if (dataBase.getForums().ContainsKey(forumId))
            {
                User moderator = dataBase.getForum(forumId).getRegUser(uname);
                bool removed = dataBase.getForum(forumId).getSubForum(subForumId).removeModerator(moderator);
                if (removed)
                    sql_init.removeSubForumModerator(forumId, subForumId, uname);
                return removed;
            
            }
            else
                return false;
        }

        public SortedDictionary<string, User> getSubForumModerators(int forumId, int subForumId)
        {
            if (dataBase.getForums().ContainsKey(forumId))
                return dataBase.getForum(forumId).getSubForum(subForumId).getModerators();
            else
                return null;
        }

     /*   public void complaint(int forumId, int subForumId, string uname)
        {
            if (dataBase.getForums().ContainsKey(forumId))
            {
                User moderator = dataBase.getForum(forumId).getRegUser(uname);
                dataBase.getForum(forumId).getSubForum(subForumId).complain(moderator);
            }
        }
     */

        public SortedDictionary<int, Thread> getSubForumThreads(int forumId, int subForumId)
        {
            if (dataBase.getForums().ContainsKey(forumId))
                return dataBase.getForum(forumId).getSubForum(subForumId).getThreads();
            else
                return null;
        }

        public void setIdForThreads(int forumId, int subForumId, int num) {
            if (dataBase.getForums().ContainsKey(forumId))
                dataBase.getForum(forumId).getSubForum(subForumId).setIdForThreads(num);
        }


        /////////////////////////////          Thread        ////////////////////////////////////////////////

        // in success return thread id, otherwise -1
        public int addThread(int forumId, int subForumId, string title, string body, User user)
        {
            if (dataBase.getForums().ContainsKey(forumId))
            {
                SubForum subForum = dataBase.getForum(forumId).getSubForum(subForumId);
                int threadId = subForum.addThread(title, body, user);
                //update database
                sql_init.addThread(threadId, forumId, subForumId, title, body, user.getUserName());
                return threadId;
            }
            else
                return -1;
        }

        public bool removeThread(int forumId, int subForumId, int threadId)
        {
            if (dataBase.getForums().ContainsKey(forumId))
            {
                SubForum subForum = dataBase.getForum(forumId).getSubForum(subForumId);
                bool removed = subForum.removeThread(threadId);
                if (removed)
                    sql_init.removeThread(forumId, subForumId, threadId);
                return removed;
            }
            else
                return false;
        }

        public void setThreadTitle(int forumId, int subForumId, int threadId, string title)
        {
            if (dataBase.getForums().ContainsKey(forumId))
            {
                SubForum subForum = dataBase.getForum(forumId).getSubForum(subForumId);
                subForum.getThread(threadId).setTitle(title);
                sql_init.updateThreadTitle(forumId, subForumId, threadId, title);
            }
      
        }

        public string getThreadTitle(int forumId, int subForumId, int threadId)
        {
            if (dataBase.getForums().ContainsKey(forumId))
            {
                SubForum subForum = dataBase.getForum(forumId).getSubForum(subForumId);
                return subForum.getThread(threadId).getTitle();
            }
            else
                return null;
        }

        public void setThreadBody(int forumId, int subForumId, int threadId, string body)
        {
            if (dataBase.getForums().ContainsKey(forumId))
            {
                SubForum subForum = dataBase.getForum(forumId).getSubForum(subForumId);
                subForum.getThread(threadId).setBody(body);
                sql_init.updateThreadBody(forumId, subForumId, threadId, body);
            }
        }

        public string getThreadBody(int forumId, int subForumId, int threadId)
        {
            if (dataBase.getForums().ContainsKey(forumId))
            {
                SubForum subForum = dataBase.getForum(forumId).getSubForum(subForumId);
                return subForum.getThread(threadId).getBody();
            }
            else
                return null;
        }

        public DateTime getThreadCTime(int forumId, int subForumId, int threadId)
        {
                SubForum subForum = dataBase.getForum(forumId).getSubForum(subForumId);
                return subForum.getThread(threadId).getTime();
        }

        public SortedDictionary<int, Post> getThreadPosts(int forumId, int subForumId, int threadId)
        {
            if (dataBase.getForums().ContainsKey(forumId))
            {
                SubForum subForum = dataBase.getForum(forumId).getSubForum(subForumId);
                return subForum.getThread(threadId).getPosts();
            }
            else
                return null;
        }

        public User getThreadPublishUser(int forumId, int subForumId, int threadId)
        {
            if (dataBase.getForums().ContainsKey(forumId))
            {
                SubForum subForum = dataBase.getForum(forumId).getSubForum(subForumId);
                return subForum.getThread(threadId).getUser();
            }
            else
                return null;
        }

        public void setIdForPosts(int forumId, int subForumId, int threadId, int idForPosts)
        {
            if (dataBase.getForums().ContainsKey(forumId))
                dataBase.getForum(forumId).getSubForum(subForumId).getThread(threadId).setIdForPosts(idForPosts);
        }

        ///////////////////////////////////////////     Posts     /////////////////////////////////////////////////////

        public int addPost(int forumId, int subForumId, int threadId, string title, string body, User user)
        {
            if (dataBase.getForums().ContainsKey(forumId))
            {
                Thread thread = dataBase.getForum(forumId).getSubForum(subForumId).getThread(threadId);
                int postId = thread.addPost(title, body, user);
                //update DataBase
                sql_init.addPost(postId, forumId, subForumId, threadId, title, body, user.getUserName());
                return postId;
            }
            else
                return -1;
        }

        public bool removePost(int forumId, int subForumId, int threadId, int postId)
        {
            if (dataBase.getForums().ContainsKey(forumId))
            {
                Thread thread = dataBase.getForum(forumId).getSubForum(subForumId).getThread(threadId);
                bool removed = thread.removePost(postId);
                if (removed)
                    sql_init.removePost(forumId, subForumId, threadId, postId);
                return removed;
            }
            else
                return false;
        }

        public Post getPost(int forumId, int subForumId, int threadId, int postId) {
            if (dataBase.getForums().ContainsKey(forumId))
            {
                Thread thread = dataBase.getForum(forumId).getSubForum(subForumId).getThread(threadId);
                return thread.getPost(postId);
            }
            else
                return null;
        }

        public void setPostTitle(int forumId, int subForumId, int threadId, int postId, string title) {
            if (dataBase.getForums().ContainsKey(forumId))
            {
                Thread thread = dataBase.getForum(forumId).getSubForum(subForumId).getThread(threadId);
                thread.getPost(postId).setTitle(title);
                sql_init.updatePostTitle(forumId, subForumId, threadId, postId, title);
            }
        }

        public string getPostTitle(int forumId, int subForumId, int threadId, int postId)
        {
            if (dataBase.getForums().ContainsKey(forumId))
            {
                Thread thread = dataBase.getForum(forumId).getSubForum(subForumId).getThread(threadId);
                return thread.getPost(postId).getTitle();
            }
            else
                return null;
        }

        public void setPostBody(int forumId, int subForumId, int threadId, int postId, string body) {
            if (dataBase.getForums().ContainsKey(forumId))
            {
                Thread thread = dataBase.getForum(forumId).getSubForum(subForumId).getThread(threadId);
                thread.getPost(postId).setBody(body);
                //update database
                sql_init.updatePostBody(forumId, subForumId, threadId, postId, body);
            }
        }

        public string getPostBody(int forumId, int subForumId, int threadId, int postId)
        {
            if (dataBase.getForums().ContainsKey(forumId))
            {
                Thread thread = dataBase.getForum(forumId).getSubForum(subForumId).getThread(threadId);
                return thread.getPost(postId).getBody();
            }
            else
                return null;
        }

        public User getPostCreatorUser(int forumId, int subForumId, int threadId, int postId)
        {
            if (dataBase.getForums().ContainsKey(forumId))
            {
                Thread thread = dataBase.getForum(forumId).getSubForum(subForumId).getThread(threadId);
                return thread.getPost(postId).getUser();
            }
            else
                return null;
        
        }


        //////////////////////////////////////////        Users       ///////////////////////////////////////////////
        public User registerUser(int forumId, string uname, string name, string lastName, string password, string email)
        {
            if (dataBase.getForums().ContainsKey(forumId))
            {
             //   Console.WriteLine("user added!");
                User user = dataBase.getForum(forumId).registerUser(uname, name, lastName, password, email);
                //update database
                sql_init.registerUser(forumId, uname, name, lastName, password, email);
                return user; 
            }
            else
                return null;
        }

        public User registerUser(int forumId, User user)
        {
            if (dataBase.getForums().ContainsKey(forumId))
            {
          //      Console.WriteLine("user added!");
                User reg_user = dataBase.getForum(forumId).registerUser(user);
                //update database
                sql_init.registerUser(forumId, reg_user.getUserName(), reg_user.getName(), reg_user.getLastName(), reg_user.getPassword(), reg_user.getEmail());
                return reg_user;
            }
            else
                return null;
        }

        public bool containsUser(int forumId, string uname)
        {
            if (dataBase.getForums().ContainsKey(forumId))
            {
                return dataBase.getForum(forumId).getUsers().ContainsKey(uname);
            }
            else
                return false;
        }

        public bool isForumUser(int forumId, User user)
        {
            if ((user != null) && dataBase.getForums().ContainsKey(forumId))
            {
                return dataBase.getForum(forumId).containsUser(user);
            }
            else
                return false;
        }

        public bool isSubForumModerator(int forumId, int subForumId, User user) {
            if ((user != null) && dataBase.getForums().ContainsKey(forumId))
            {
                return dataBase.getForum(forumId).getSubForum(subForumId).isModerator(user);
            }
            else
                return false;
        }

        public bool isSubForumModerator(int forumId, int subForumId, string user)
        {
            if ((user != null) && dataBase.getForums().ContainsKey(forumId))
            {
                return dataBase.getForum(forumId).getSubForum(subForumId).isModerator(user);
            }
            else
                return false;
        }

        public User getUser(int forumId, string uname)
        {
            if ((uname != null) && dataBase.getForums().ContainsKey(forumId))
            {
                return dataBase.getForum(forumId).getRegUser(uname);
            }
            else
                return null;
        
        }

        //Check if user is a member (for login).
        public bool isMember(int forumId, string username, string password)
        {
            if ((username != null) && dataBase.getForums().ContainsKey(forumId))
            {
                User user = dataBase.getForum(forumId).getRegUser(username);
                return user.getPassword().Equals(password);
            }
            else
                return false;
        }

        public string getLastName(int forumId, string username) {
            if ((username != null) && dataBase.getForums().ContainsKey(forumId))
            {
                return dataBase.getForum(forumId).getRegUser(username).getLastName();
            }
            else
                return null;
        }

        public string getEmail(int forumId, string username)
        {
            if ((username != null) && dataBase.getForums().ContainsKey(forumId))
            {
                return dataBase.getForum(forumId).getRegUser(username).getEmail();
            }
            else
                return null;
        }

        //Return the user's friends. 
        public SortedDictionary<string, User> getFriends(int forumId, string username)
        {
            if ((username != null) && dataBase.getForums().ContainsKey(forumId))
            {
                return dataBase.getForum(forumId).getRegUser(username).getFriends();
            }
            else
                return null;
        }

        public bool addFriend(int forumId, string username, string friend)
        {
            if ((username != null) && dataBase.getForums().ContainsKey(forumId))
            {
                User newFriend = dataBase.getForum(forumId).getRegUser(friend);
                bool added = dataBase.getForum(forumId).getRegUser(username).addFriend(newFriend);
                //update database
                if (added)
                    sql_init.addFriend(forumId, username, friend);
                return added;
            }
            else
                return false;
        
        }

        public bool removeFriend(int forumId, string username, string friend)
        {
            if ((username != null) && dataBase.getForums().ContainsKey(forumId))
            {
                bool removed = dataBase.getForum(forumId).getRegUser(username).removeFriend(friend);
                //update database
                if (removed)
                    sql_init.removeFriend(forumId, username, friend);
                return removed;
            }
            else
                return false;
        }

        public int getModeratorComplaints(int forumId, int subForumId, User moderator)
        {
            if ((moderator != null) && dataBase.getForums().ContainsKey(forumId))
            {
                return dataBase.getForum(forumId).getSubForum(subForumId).getModeratorComplaints(moderator);
            }
            else
                return 0;

        }

        public int getModeratorComplaints(int forumId, int subForumId, string moderator) {
            if ((moderator != null) && dataBase.getForums().ContainsKey(forumId))
            {
                User user = dataBase.getForum(forumId).getRegUser(moderator);
                return dataBase.getForum(forumId).getSubForum(subForumId).getModeratorComplaints(user);
            }
            else
                return 0;
        }

        //remove moderator in sub forum. Return true in success, otherwise false.
        public bool removeModerator(int forumId, int subForumId, string m_name)
        {
            if ((m_name != null) && dataBase.getForums().ContainsKey(forumId))
            {
                bool removed = dataBase.getForum(forumId).getSubForum(subForumId).removeModerator(m_name);
                //update database
                if (removed)
                    sql_init.removeModerator(forumId, subForumId, m_name);
                return removed;
            }
            else
                return false;
        }

        public void setModeratorComplaints(int forumId, int subForumId, string moderator, int complaint)
        {
            if ((moderator != null) && dataBase.getForums().ContainsKey(forumId))
            {
                dataBase.getForum(forumId).getSubForum(subForumId).setModeratorComplaints(moderator, complaint);
                //update database
                sql_init.updateModeratorComplaints(forumId, subForumId, moderator, complaint);
            }
        }



      ////////////////////              Permissions         ///////////////////////////////

       //only director has permission to add new forum (add new forum)
        public bool addForumPermission(User user) {
            return user.getUserName().Equals("Gilad");
        }
        //only director and admin of the forum have permission to change forum (set title)
        public bool changeForumPermission(int forumId, User user) {
            return (user.getUserName().Equals("Gilad") || user.getUserName().Equals(getForumAdmin(forumId).getUserName()));
        }

        //only director and admin of the forum have permission to change subforum (add and remove subforum, change title, remove moderator, add moderator)
        public bool changeSubForumPermission(int forumId, User user) {
            return (user.getUserName().Equals("Gilad") || user.getUserName().Equals(getForumAdmin(forumId).getUserName()));
        }

        //only director, admin , moderator or publish user of the subforum have permission to change thread (add and remove thread, change title and body,  )
        public bool changeThreadPermission(int forumId, int subforumId, int threadId, User user)
        {
            return (user.getUserName().Equals("Gilad")
                || user.getUserName().Equals(getForumAdmin(forumId).getUserName())
                || dataBase.getForum(forumId).getSubForum(subforumId).isModerator(user)
                || user.getUserName().Equals(dataBase.getForum(forumId).getSubForum(subforumId).getThread(threadId).getUser().getUserName()));
        }

      //all regestred users have permission to publish thread 
       public bool addThreadPermission(int forumId, User user) {
           return dataBase.getForum(forumId).containsUser(user);
        }

       //only director, admin , moderator (in subforum) or publish user of the post have permission to change post (add and remove post, change title and body,  )
       public bool changePostPermission(int forumId, int subforumId, int threadId, int postId, User user)
       {
           return (user.getUserName().Equals("Gilad")
               || user.getUserName().Equals(getForumAdmin(forumId).getUserName())
               || dataBase.getForum(forumId).getSubForum(subforumId).isModerator(user)
               || user.getUserName().Equals(dataBase.getForum(forumId).getSubForum(subforumId).getThread(threadId).getPost(postId).getUser().getUserName()));
       }

       //all regestred users have permission to publish post
       public bool addPostPermission(int forumId, User user)
       {
           return dataBase.getForum(forumId).containsUser(user);
       }

    }
}
